package org.jtb.neoapi;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.util.Log;

public class NeoFetcher {
	private static final String URL = "http://neo.jpl.nasa.gov/ca/";

	private static final Pattern NEO_PATTERN = Pattern
			.compile("\\s+<td nowrap align=\"center\"><font size=\"-1\"><a href=\"(http://ssd\\.jpl\\.nasa\\.gov/sbdb\\.cgi\\?sstr=([0-9A-Z ]+));orb=1\" target=\"_blank\">.*");
	private static final Pattern DATE_PATTERN = Pattern
			.compile("\\s+<td nowrap align=\"left\"><font size=\"-1\">&nbsp;([a-zA-Z0-9-]+)</font></td>.*");
	private static final Pattern MISS_DISTANCE_PATTERN = Pattern
			.compile("\\s+<td nowrap align=\"center\"><font size=\"-1\">([\\d\\.]+)</font></td>.*");
	private static final Pattern SIZE_PATTERN = Pattern
			.compile("\\s+<td nowrap align=\"center\"><font size=\"-1\">([\\d\\.]+ k?m) - ([\\d\\.]+ k?m)<!-- H=(.*) --></font></td>");
	private static final Pattern SIZE_PATTERN_SINGLE = Pattern
			.compile("\\s+<td nowrap align=\"center\"><font size=\"-1\">([\\d\\.]+ k?m)\\s*</font></td>");
	private static final Pattern VELOCITY_PATTERN = Pattern
			.compile("\\s+<td nowrap align=\"center\"><font size=\"-1\">([\\d\\.]+)</font></td>.*");

	public static List<Neo> fetch() throws Throwable {
		BufferedReader reader = null;
		String line;

		try {
			URL u = new URL(URL);
			HttpURLConnection uc = (HttpURLConnection) u.openConnection();
			uc.setReadTimeout(30 * 1000); // 30 seconds

			if (uc.getResponseCode() != 200) {
				// TODO: android log
				return null;
			}

			reader = new BufferedReader(new InputStreamReader(
					uc.getInputStream(), "ISO-8859-1"), 8192);
			reader.readLine();

			List<Neo> neos = new ArrayList<Neo>();
			while ((line = reader.readLine()) != null) {
				Matcher m = NEO_PATTERN.matcher(line);
				if (m.matches()) {
					boolean valid = true;
					Neo neo = new Neo();

					String url = m.group(1);
					if (url == null) {
						valid = false;
					} else {
						neo.setUrl(url);
					}

					String name = m.group(2);
					if (name == null) {
						valid = false;
					} else {
						neo.setName(name);
					}

					line = reader.readLine();
					m = DATE_PATTERN.matcher(line);
					if (m.matches()) {
						String date = m.group(1);
						if (date == null) {
							valid = false;
						} else {
							neo.setDate(date);
						}
					} else {
						Log.d("neodroid", "could not parse line: " + line);
						valid = false;
					}

					line = reader.readLine();
					m = MISS_DISTANCE_PATTERN.matcher(line);
					if (m.matches()) {
						String dist = m.group(1);
						if (dist == null) {
							valid = false;
						} else {
							neo.setMissDistanceAu(dist);
						}
					} else {
						Log.d("neodroid", "could not parse line: " + line);
						valid = false;
					}

					line = reader.readLine();
					m = MISS_DISTANCE_PATTERN.matcher(line);
					if (m.matches()) {
						String dist = m.group(1);
						if (dist == null) {
							valid = false;
						} else {
							neo.setMissDistanceLd(dist);
						}
					} else {
						Log.d("neodroid", "could not parse line: " + line);
						valid = false;
					}

					line = reader.readLine();
					m = SIZE_PATTERN.matcher(line);
					if (m.matches()) {
						String min = m.group(1);
						if (min == null) {
							valid = false;
						} else {
							neo.setMinDiameter(min);
						}

						String max = m.group(2);
						if (max == null) {
							valid = false;
						} else {
							neo.setMaxDiameter(max);
						}

						String mag = m.group(3);
						if (mag == null) {
							valid = false;
						} else {
							neo.setMagnitude(mag);
						}
					} else {
						m = SIZE_PATTERN_SINGLE.matcher(line);
						if (m.matches()) {
							String d = m.group(1);
							if (d == null) {
								valid = false;
							} else {
								neo.setMinDiameter(d);
								neo.setMaxDiameter(d);
								neo.setMagnitude(-1);
							}
						} else {
							Log.d("neodroid", "could not parse line: " + line);
							valid = false;
						}
					}

					line = reader.readLine();

					line = reader.readLine();
					m = VELOCITY_PATTERN.matcher(line);
					if (m.matches()) {
						String vel = m.group(1);
						if (vel == null) {
							valid = false;
						} else {
							neo.setVelocity(vel);
						}
					} else {
						Log.d("neodroid", "could not parse line: " + line);
						valid = false;
					}

					if (valid) {
						neos.add(neo);
					}
				}
			}

			return neos;
		} catch (Throwable t) {
			Log.e("neodroid", "could not parse page", t);
			throw t;
		} finally {
			try {
				if (reader != null) {
					reader.close();
				}
			} catch (IOException ioe) {
				Log.w("neodroid", ioe);
			}
		}

	}
}
